package com.shujia.wyh.day15;

/*
    protected void finalize()
        protected void finalize() throws Throwable
        当垃圾收集确定不再有对该对象的引用时，垃圾收集器在对象上调用该对象。
        一个子类覆盖了处理系统资源或执行其他清理的finalize方法。
        简单来说，这个方法就是用来做垃圾回收的，但是，什么时候回收我们并不清楚。

    protected Object clone() throws CloneNotSupportedException
        创建并返回此对象的副本。
        “复制”的精确含义可能取决于对象的类。 一般的意图是，对于任何对象x ，表达式：
    如果此对象的类不实现接口Cloneable ，则抛出CloneNotSupportedException 。
    Cloneable接口中没有任何的成员变量和成员方法，像这样的接口称之为标记接口。
    将其所有字段初始化为完全符合该对象的相应字段的内容，就像通过赋值一样。
    这些字段的内容本身不被克隆。 因此，该方法执行该对象的“浅拷贝”，而不是“深度拷贝”操作。

 */
public class ObjectDemo2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student2 s1 = new Student2();
        s1.setName("xiaohu");
        s1.setAge(18);
        //今后直接打印一个对象的名字，其实是默认使用该对象的toString()方法
        //今后如果打印一个对象的名字，结果不是地址值你能看懂，说明该类重写了toString()方法
        System.out.println(s1);
//        System.out.println(s1.toString());
        System.out.println("=======================================");
        //clone() 在 java.lang.Object 中是 protected 访问控制
        //java: 未报告的异常错误java.lang.CloneNotSupportedException; 必须对其进行捕获或声明以便抛出
        //java.lang.CloneNotSupportedException: com.shujia.wyh.day15.Student2
        Object obj = s1.clone();  // 这里其实是多态的形式接收的
        System.out.println(obj);
        //向下转型
        Student2 cloneStudent = (Student2) obj;
        System.out.println(cloneStudent.getName() + "---" + cloneStudent.getAge());
        System.out.println(s1.getName() + "---" + s1.getAge());
        System.out.println("==================================================");
        s1.setName("小虎");
        System.out.println(cloneStudent.getName() + "---" + cloneStudent.getAge());
        System.out.println(s1.getName() + "---" + s1.getAge());
        System.out.println("==================================================");
        //java中有不同的拷贝方式，大致上分为两种：深拷贝，浅拷贝（面试必问）
        //问题：Object类中clone方法是浅拷贝还是深拷贝
        //第一步：什么是深浅拷贝？
        //浅拷贝：指的是在拷贝完后，会产生一个与原来地址值不一样的对象，但是如果对象中存在引用数据类型的成员变量，
        //      该成员变量拷贝后指向的依旧是同一个对象，其他基本数据类型的变量值是一样的
        //深拷贝：指的是在拷贝完后，本身会产生一个与原来地址值不一样的对象，并且如果对象中存在引用数据类型的成员变量
        //      拷贝后与拷贝前的成员变量地址值也是不一样的。
        System.out.println("=========验证Object类中clone方法是浅拷贝还是深拷贝==========================");
        //创建一个拷贝前的对象
        Demo demo = new Demo();
        Student2 copyQian = new Student2("xiaohu", 18, demo);
        //调用clone方法拷贝
        Object obj2 = copyQian.clone();
        //向下转型
        Student2 copyHou = (Student2) obj2;
        //比较拷贝前与拷贝后的地址值
        System.out.println(copyQian.hashCode() == copyHou.hashCode());
        //比较拷贝前与拷贝后的成员变量demo对象的地址值
        Demo copyQianDemo = copyQian.getDemo();
        Demo copyHouDemo = copyHou.getDemo();
        System.out.println(copyQianDemo.hashCode() == copyHouDemo.hashCode()); //true
        //通过观察发现，Object类中的clone方法是浅拷贝


    }
}
